import { Prefab } from 'cc';
import { bundleManager } from './bundleManager';
import { resLoader } from './resload';
import { nodePoolManager, INodePoolConfig } from '../nodepool/NodepoolManager';

/**
 * 资源包与节点池集成配置
 */
export interface IBundlePoolConfig extends INodePoolConfig {
    /** 资源包名称 */
    bundleName?: string;
    /** 预制体路径 */
    prefabPath: string;
}

/**
 * 资源包节点池管理器
 * 集成资源包管理器和节点池管理器，提供统一的资源和节点池管理
 */
export class BundlePoolIntegration {
    private static _instance: BundlePoolIntegration;

    /** 池ID到资源包名称的映射 */
    private readonly poolToBundleMap: Map<string, string> = new Map();

    /** 池ID到预制体路径的映射 */
    private readonly poolToPrefabMap: Map<string, string> = new Map();

    private constructor() {}

    /**
     * 获取单例实例
     */
    public static getInstance(): BundlePoolIntegration {
        if (!BundlePoolIntegration._instance) {
            BundlePoolIntegration._instance = new BundlePoolIntegration();
        }
        return BundlePoolIntegration._instance;
    }

    /**
     * 创建资源包节点池
     * 自动加载资源包并创建节点池
     * 
     * @param poolId 节点池唯一标识
     * @param config 配置选项
     * @example
     * await bundlePool.createPool('enemy', {
     *     bundleName: 'game',
     *     prefabPath: 'prefabs/enemy',
     *     preloadCount: 10,
     *     maxCount: 50,
     * });
     */
    public async createPool(poolId: string, config: IBundlePoolConfig): Promise<boolean> {
        if (!poolId) {
            throw new Error('节点池ID不能为空');
        }

        if (!config.prefabPath) {
            throw new Error('预制体路径不能为空');
        }

        const bundleName = config.bundleName || 'resources';

        try {
            // 1. 确保资源包已加载
            let bundle = bundleManager.getBundle(bundleName);
            if (!bundle) {
                console.log(`[BundlePool] 加载资源包: ${bundleName}`);
                bundle = await bundleManager.loadBundle(bundleName);
                if (!bundle) {
                    throw new Error(`加载资源包 ${bundleName} 失败`);
                }
            }

            // 2. 加载预制体
            console.log(`[BundlePool] 加载预制体: ${config.prefabPath}`);
            const prefab = await resLoader.loadAsync<Prefab>(bundleName, config.prefabPath, Prefab);
            
            if (!prefab) {
                throw new Error(`加载预制体 ${config.prefabPath} 失败`);
            }

            // 3. 创建节点池
            const poolConfig: INodePoolConfig = {
                preloadCount: config.preloadCount,
                maxCount: config.maxCount,
                enableStats: config.enableStats,
                onNodeCreate: config.onNodeCreate,
                onNodeReuse: config.onNodeReuse,
                onNodeRecycle: config.onNodeRecycle,
            };

            nodePoolManager.createPool(poolId, prefab, poolConfig);

            // 4. 记录映射关系
            this.poolToBundleMap.set(poolId, bundleName);
            this.poolToPrefabMap.set(poolId, config.prefabPath);

            // 5. 增加资源包引用
            bundleManager.retainBundle(bundleName);

            console.log(`[BundlePool] 节点池 ${poolId} 创建成功`);
            return true;

        } catch (error) {
            console.error(`[BundlePool] 创建节点池 ${poolId} 失败:`, error);
            return false;
        }
    }

    /**
     * 批量创建资源包节点池
     * @param configs 配置数组
     */
    public async createPools(configs: Array<{ poolId: string; config: IBundlePoolConfig }>): Promise<Map<string, boolean>> {
        const results = new Map<string, boolean>();

        for (const { poolId, config } of configs) {
            const success = await this.createPool(poolId, config);
            results.set(poolId, success);
        }

        return results;
    }

    /**
     * 创建节点池并预加载
     * @param poolId 节点池ID
     * @param config 配置选项
     */
    public async createPoolAndPreload(poolId: string, config: IBundlePoolConfig): Promise<boolean> {
        const success = await this.createPool(poolId, config);
        
        if (success) {
            await nodePoolManager.preloadPool(poolId);
        }

        return success;
    }

    /**
     * 移除节点池并释放资源
     * @param poolId 节点池ID
     * @param unloadBundle 是否卸载资源包
     */
    public removePool(poolId: string, unloadBundle: boolean = false): void {
        const bundleName = this.poolToBundleMap.get(poolId);
        const prefabPath = this.poolToPrefabMap.get(poolId);

        // 清理节点池
        if (nodePoolManager.hasPool(poolId)) {
            nodePoolManager.removePool(poolId);
        }

        // 释放预制体资源
        if (bundleName && prefabPath) {
            resLoader.release(prefabPath, bundleName);

            // 减少资源包引用
            bundleManager.releaseBundle(bundleName, unloadBundle);
        }

        // 清理映射关系
        this.poolToBundleMap.delete(poolId);
        this.poolToPrefabMap.delete(poolId);

        console.log(`[BundlePool] 节点池 ${poolId} 已移除`);
    }

    /**
     * 移除所有节点池
     * @param unloadBundles 是否卸载资源包
     */
    public removeAllPools(unloadBundles: boolean = false): void {
        const poolIds = Array.from(this.poolToBundleMap.keys());
        
        poolIds.forEach(poolId => {
            this.removePool(poolId, unloadBundles);
        });

        console.log('[BundlePool] 所有节点池已移除');
    }

    /**
     * 获取节点池所属的资源包
     * @param poolId 节点池ID
     */
    public getPoolBundle(poolId: string): string | undefined {
        return this.poolToBundleMap.get(poolId);
    }

    /**
     * 获取节点池的预制体路径
     * @param poolId 节点池ID
     */
    public getPoolPrefabPath(poolId: string): string | undefined {
        return this.poolToPrefabMap.get(poolId);
    }

    /**
     * 检查节点池是否存在
     * @param poolId 节点池ID
     */
    public hasPool(poolId: string): boolean {
        return this.poolToBundleMap.has(poolId);
    }

    /**
     * 获取所有节点池ID
     */
    public getAllPoolIds(): string[] {
        return Array.from(this.poolToBundleMap.keys());
    }

    /**
     * 按资源包分组获取节点池
     */
    public getPoolsByBundle(): Map<string, string[]> {
        const bundleGroups = new Map<string, string[]>();

        this.poolToBundleMap.forEach((bundleName, poolId) => {
            if (!bundleGroups.has(bundleName)) {
                bundleGroups.set(bundleName, []);
            }
            bundleGroups.get(bundleName)!.push(poolId);
        });

        return bundleGroups;
    }

    /**
     * 卸载资源包并清理相关节点池
     * @param bundleName 资源包名称
     */
    public unloadBundleWithPools(bundleName: string): void {
        const poolIds: string[] = [];

        // 找出所有属于该资源包的节点池
        this.poolToBundleMap.forEach((bundle, poolId) => {
            if (bundle === bundleName) {
                poolIds.push(poolId);
            }
        });

        // 移除节点池
        poolIds.forEach(poolId => {
            this.removePool(poolId, false);
        });

        // 卸载资源包
        bundleManager.unloadBundle(bundleName);

        console.log(`[BundlePool] 资源包 ${bundleName} 及其 ${poolIds.length} 个节点池已卸载`);
    }

    /**
     * 预热资源包的所有节点池
     * @param bundleName 资源包名称
     */
    public async preloadBundlePools(bundleName: string): Promise<void> {
        const poolIds: string[] = [];

        this.poolToBundleMap.forEach((bundle, poolId) => {
            if (bundle === bundleName) {
                poolIds.push(poolId);
            }
        });

        if (poolIds.length > 0) {
            await nodePoolManager.preloadPools(poolIds);
            console.log(`[BundlePool] 资源包 ${bundleName} 的 ${poolIds.length} 个节点池已预加载`);
        }
    }

    /**
     * 打印节点池和资源包映射信息
     */
    public printPoolInfo(): void {
        console.log('======== 节点池资源包映射 ========');
        
        const bundleGroups = this.getPoolsByBundle();
        
        bundleGroups.forEach((poolIds, bundleName) => {
            console.log(`\n[资源包: ${bundleName}]`);
            poolIds.forEach(poolId => {
                const prefabPath = this.poolToPrefabMap.get(poolId);
                const stats = nodePoolManager.getPoolStats(poolId);
                console.log(`  - ${poolId}`);
                console.log(`    预制体: ${prefabPath}`);
                if (stats) {
                    console.log(`    池大小: ${stats.poolSize}, 活跃: ${stats.activeCount}, 命中率: ${(stats.hitRate * 100).toFixed(2)}%`);
                }
            });
        });
        
        console.log('\n================================');
    }

    /**
     * 清理所有数据
     */
    public clear(): void {
        this.removeAllPools(false);
        this.poolToBundleMap.clear();
        this.poolToPrefabMap.clear();
    }
}

/**
 * 导出单例实例
 */
export const bundlePool = BundlePoolIntegration.getInstance();

